package com.rtsapp.server.domain.mysql.hibernate.impl;


import com.rtsapp.server.domain.mysql.hibernate.impl.op.InsertUpdateDeleteTask;
import com.rtsapp.server.logger.Logger;

import com.rtsapp.server.domain.mysql.hibernate.IEntityTransaction;
import com.rtsapp.server.domain.mysql.hibernate.impl.op.HibernateTransactionTask;

import java.io.Serializable;
import java.util.List;


/**
 * 这个类实现了IEntityTransaction接口，用于对数据源进行增删改查操作。 其中增删改使用队列完成，而查询数据和查询作用数量为实时操作。
 * 对事物的开启、关闭、提交和回滚
 *
 * @author zhangbin
 */
public class AysncTransaction implements IEntityTransaction {

	private static final Logger logger =com.rtsapp.server.logger.LoggerFactory.getLogger(AysncTransaction.class);

	private HibernateTransactionTask transactionTask = null;

	private IEntityTransaction directTransaction= null;

	private final AsyncTransactionWorker worker;

	public  AysncTransaction(  AsyncTransactionWorker  worker ) {
		this.worker = worker;
	}


	@Override
	public void begin() {

	}

	@Override
	public void close() {

		if( directTransaction != null ){
			directTransaction.close();
			directTransaction = null;
		}

		if( transactionTask != null ){
			transactionTask = null;
		}
		
	}

	@Override
	public void commit() {
		
		if(  directTransaction != null ){
			directTransaction.commit();
		}
		
		if ( transactionTask != null && !transactionTask.isEmpty() ) {
			if( transactionTask.taskSize( ) > 1 ){
				this.worker.put( transactionTask );
			}else{
				this.worker.put( transactionTask.firstTask( ) );
			}
		}
	}
	
	

	@Override
	public void rollback() {

		if( directTransaction != null ){
			directTransaction.rollback();
		}

		if ( transactionTask != null ) {
			transactionTask = null;
		}

	}
	
	private IEntityTransaction getDirectTransaction(){
		
		if( directTransaction == null ){
			directTransaction = new DirectTransaction();
			directTransaction.begin();
			
			logger.info( "directTransaction begin" );
		}
		
		return directTransaction;
	}
	
	
	private HibernateTransactionTask getAysncTransaction( ){
		
		if( transactionTask == null ){
			
			transactionTask = new HibernateTransactionTask( );

			logger.info( "create HibernateTransactionTask" );
		}
		
		return transactionTask;
	}
	
	


	@Override
	public Object get(Class<?> entityClass, Serializable id) {
		return getDirectTransaction( ).get(entityClass, id);
	}
	
	

	@Override
	public List<?> get(Class<?> entityClass, List<Serializable> idList) {
		return getDirectTransaction().get(entityClass, idList);
	}

	@Override
	public List<?> get(Class<?> entityClass, Serializable... idList) {
		return getDirectTransaction().get(entityClass, idList);
	}

	
	@Override
	public int executeUpdate(String hql, Object... objects) {
		
		return getDirectTransaction( ).executeUpdate(hql, objects);
	}
	
	

	@Override
	public Object queryUnique(String hql, Object... objects) {
		
		return getDirectTransaction( ).queryUnique(hql, objects);
	}

	@Override
	public List<?> queryList(String hql, Object... objects) {
		
		return getDirectTransaction( ).queryList(hql, objects);
	}

	@Override
	public List<?> queryListLimit(int firstResult, int maxResults, String hql, Object... objects) {
		return getDirectTransaction( ).queryListLimit(firstResult, maxResults, hql, objects);		
	}


	@Override
	public void insert(Object entity) {
		
		getAysncTransaction( ).addOperation( new InsertUpdateDeleteTask( AysncOperation.OperationType.INSERT, entity ) );
		
	}
	

	@Override
	public void insert(List<?> entityList) {
		getAysncTransaction( ).addOperation( new InsertUpdateDeleteTask( AysncOperation.OperationType.INSERT, entityList ) );
	}

	@Override
	public void insert(Object... entityList) {
		getAysncTransaction( ).addOperation( new InsertUpdateDeleteTask( AysncOperation.OperationType.INSERT, entityList ) );
	}

	
	@Override
	public void update(Object entity) {
		getAysncTransaction( ).addOperation( new InsertUpdateDeleteTask( AysncOperation.OperationType.UPDATE, entity ) );
	}

	@Override
	public void update(List<?> entityList) {
		getAysncTransaction( ).addOperation( new InsertUpdateDeleteTask( AysncOperation.OperationType.UPDATE, entityList ) );
	}

	@Override
	public void update(Object... entityList) {
		getAysncTransaction( ).addOperation( new InsertUpdateDeleteTask( AysncOperation.OperationType.UPDATE, entityList ) );
	}

	@Override
	public void delete(Object entity) {
		getAysncTransaction( ).addOperation( new InsertUpdateDeleteTask( AysncOperation.OperationType.DELETE, entity ) );
	}

	@Override
	public void delete(List<?> entityList) {
		getAysncTransaction( ).addOperation( new InsertUpdateDeleteTask( AysncOperation.OperationType.DELETE, entityList ) );
	}

	@Override
	public void delete(Object... entityList) {
		getAysncTransaction( ).addOperation( new InsertUpdateDeleteTask( AysncOperation.OperationType.DELETE, entityList ) );
	}
	
}
